﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;

namespace NczControlLibrary.Panels {
    public class NczWrapPanel : Panel {
        Size measureSize;
        protected override Size MeasureOverride(Size availableSize) {
            this.measureSize = availableSize;
            foreach (var item in this.Children) {
                item.Measure(availableSize);
            }
            return base.MeasureOverride(availableSize);
        }
        protected override Size ArrangeOverride(Size finalSize) {
            int index;
            index = 1;
            var width = finalSize.Width;
            var height = finalSize.Height;
            var colwidthtotal = 0d;
            var colwlist = new List<double>();
            colwlist.Add(ColumnDistance);
            var rowheighttotal = 0d;
            var rowhlist = new List<double>();
            double itemx,itemy;
            itemy = RowDistance; itemx = ColumnDistance;

            foreach (var item in this.Children) {
                rowheighttotal = item.DesiredSize.Height + this.RowDistance;
                rowhlist.Add(rowheighttotal);
                colwidthtotal += item.DesiredSize.Width + this.ColumnDistance;
                colwlist.Add(colwidthtotal);
                if (colwidthtotal < width) {
                    //confirm x coordinate
                    itemx = colwlist[index - 1];
                } else {
                    var max = rowhlist.Max();
                    itemy += max + RowDistance;
                    if (itemy + max < height) {
                        //confirm y coordinate
                        itemx = ColumnDistance;
                        rowhlist.Clear();
                        colwlist.Clear();
                        colwlist.Add(ColumnDistance);
                        rowheighttotal = 0d;
                        colwidthtotal = item.DesiredSize.Width + this.ColumnDistance;
                        colwlist.Add(colwidthtotal);
                        index = 1;
                    } else {
                        item.Arrange(new Rect(0,0,0,0));
                        continue;
                    }
                }
                item.Arrange(new Rect(new Point(itemx,itemy),item.DesiredSize));
                index++;
            }
            return base.ArrangeOverride(finalSize);
        }
        public NczWrapPanel() {
            this.SizeChanged += new SizeChangedEventHandler(RdpWrapPanel_SizeChanged);
            this.MouseEnter += new MouseEventHandler(RdpWrapPanel_MouseEnter);
            this.MouseLeave += new MouseEventHandler(RdpWrapPanel_MouseLeave);
        }

        void RdpWrapPanel_MouseLeave(object sender,MouseEventArgs e) {
            this.OnMouseEnter(e);
        }

        void RdpWrapPanel_MouseEnter(object sender,MouseEventArgs e) {
            this.OnMouseLeave(e);
        }

        void RdpWrapPanel_SizeChanged(object sender,SizeChangedEventArgs e) {
            //this.MeasureOverride(measureSize);
            //this.ArrangeOverride(this.DesiredSize);
        }
        protected virtual void OnMouseLeave(MouseEventArgs e) { }
        protected virtual void OnMouseEnter(MouseEventArgs e) { }
        #region dependency properties
        public static readonly DependencyProperty f2 = DependencyProperty.Register("RowDistance",typeof(double),typeof(NczWrapPanel),new PropertyMetadata(5d,
(o,k) => { }));
        public double RowDistance { get { return (double)this.GetValue(f2); } set { this.SetValue(f2,value); } }
        public static readonly DependencyProperty f1 = DependencyProperty.Register("ColumnDistance",typeof(double),typeof(NczWrapPanel),new PropertyMetadata(3d,
(o,k) => { }));
        public double ColumnDistance { get { return (double)this.GetValue(f1); } set { this.SetValue(f1,value); } }
        #endregion
    }
}
